package com.ineatconseil.yougo.utils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ineatconseil.yougo.beans.DayInformation;

/**
 * Load year/month information.
 * 
 * @author johanblo
 * 
 */
public class CustomCalendar {

	/**
	 * Default logger.
	 */
	private static final Log LOGGER = LogFactory.getLog(CustomCalendar.class);

	/**
	 * Calendar use for compute month information.
	 */
	private Calendar cal;

	/**
	 * Current month.
	 */
	private int month;

	/**
	 * Current year.
	 */
	private int year;

	/**
	 * Number of working days.
	 */
	private int workingDaysCount;

	/**
	 * Days information for the year and the month.
	 */
	private List<DayInformation> dayInfo = null;

	/**
	 * Default constructor. Create the information for actual year and actual month.
	 */
	public CustomCalendar() {
		super();
		this.year = 0;
		this.month = 0;
		createCalendar();
	}

	/**
	 * Constructor.
	 * 
	 * @param year
	 *            the year.
	 * @param month
	 *            the month.
	 */
	public CustomCalendar(int year, int month) {
		super();
		this.year = year;
		this.month = month;
		createCalendar();
	}

	/**
	 * Create the calendar.
	 */
	private void createCalendar() {
		cal = Calendar.getInstance();
		if (this.month != 0) {
			cal.set(Calendar.MONTH, month - 1);
		}
		if (this.year != 0) {
			cal.set(Calendar.YEAR, year);
		}
		cal.set(Calendar.DATE, 1);
		cal.set(Calendar.HOUR, 11);

		this.month = cal.get(Calendar.MONTH) + 1;
		this.year = cal.get(Calendar.YEAR);

		loadCurrentMonthInfos();

		LOGGER.info("New calendar created for [" + this.month + "/" + this.year + "]");
	}

	/**
	 * Load the month information.
	 */
	private void loadCurrentMonthInfos() {

		dayInfo = new ArrayList<DayInformation>();
		for (int i = 1; i <= cal.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
			cal.set(Calendar.DATE, i);
			String label = convertLabelDay(cal.get(Calendar.DAY_OF_WEEK));
			boolean workingDay = isWorkingDay(label, i);
			if (workingDay) {
				workingDaysCount++;
			}
			dayInfo.add(new DayInformation(label, i, workingDay));
		}

	}

	/**
	 * Converti la valeur numérique du jour de la semaine en libellé.
	 * 
	 * @param calConstant
	 *            valeur numérique du jour dans la semaine
	 * @return libellé du jour dans la semaine (L, M, M, J, V, S, D)
	 */
	private String convertLabelDay(int calConstant) {
		switch (calConstant) {
		case Calendar.MONDAY:
			return "Lun";

		case Calendar.TUESDAY:
			return "Mar";

		case Calendar.WEDNESDAY:
			return "Mer";

		case Calendar.THURSDAY:
			return "Jeu";

		case Calendar.FRIDAY:
			return "Ven";

		case Calendar.SATURDAY:
			return "Sam";

		case Calendar.SUNDAY:
			return "Dim";

		default:
			return "";

		}

	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public List<DayInformation> getDayInfo() {
		return dayInfo;
	}

	public void setDayInfo(List<DayInformation> dayInfo) {
		this.dayInfo = dayInfo;
	}

	/**
	 * Return if the given day is a working day or not.
	 * 
	 * @param label
	 *            The label of the day.
	 * @param currentDay
	 *            The value of the day.
	 * @return true if day is a working day.
	 */
	private boolean isWorkingDay(String label, int currentDay) {
		return (!label.equals("") && !label.equals("Sam") && !label.equals("Dim"));
	}

	/**
	 * Get the {@link DayInformation} for the current list by its day value.
	 * 
	 * @param dayValue
	 *            the day value.
	 * @return the corresponding {@link DayInformation}.
	 */
	public DayInformation getDayInformation(int dayValue) {

		for (DayInformation day : this.dayInfo) {
			if (day.getDay() == dayValue) {
				return day;
			}
		}
		return null;
	}

	public void setWorkingDaysCount(int workingDaysCount) {
		this.workingDaysCount = workingDaysCount;
	}

	public int getWorkingDaysCount() {
		return workingDaysCount;
	}

}
